#ifndef MAINBUS_H
#define MAINBUS_H

#include <vector>
#include <unordered_map>
#include <functional>
#include <memory>
#include "Cartridge.h"
#include "Mapper.h"
#include "pch.h"

PNE_NAMESPACE_BEGIN
enum class IORegisters
{
    PPUCTRL = 0x2000,
    PPUMASK,
    PPUSTATUS,
    OAMADDR,
    OAMDATA,
    PPUSCROL,
    PPUADDR,
    PPUDATA,
    OAMDMA = 0x4014,
    JOY1 = 0x4016,
    JOY2 = 0x4017,
};

struct IORegistersHasher
{
    std::size_t operator()(PROJECT_NAME::IORegisters const &reg) const noexcept
    {
        return std::hash<std::uint32_t>{}(static_cast<int>(reg));
    }
};

struct MainBus
{
public:
    MainBus();
    Byte Read(Address addr);
    void Write(Address addr, Byte value);
    bool SetMapper(Mapper *mapper);
    bool SetWriteCallback(IORegisters reg, std::function<void(Byte)> callback);
    bool SetReadCallback(IORegisters reg, std::function<Byte(void)> callback);
    const Byte *GetPagePtr(Byte page);

private:
    std::vector<Byte> m_RAM;
    std::vector<Byte> m_extRAM;
    Mapper *m_mapper;

    std::unordered_map<IORegisters, std::function<void(Byte)>, IORegistersHasher> m_writeCallbacks;
    std::unordered_map<IORegisters, std::function<Byte(void)>, IORegistersHasher> m_readCallbacks;
};
PNE_NAMESPACE_END // namespace

#endif // MAINBUS_H

    // DONE